# -*- coding: utf-8 -*-
import os
import re
import json
from uuid import uuid1 as guid
import time
from datetime import datetime as DateTime
from decimal import Decimal
import hashlib

timezone_choices = (
		(80, 'UTC+8 北京/重庆/香港/乌鲁木齐'),								
		(-80, 'UTC-8 Pacific Time(US & Canada)'),
		(-60, 'UTC-6 Central Time(US & Canada) / Central America'),
		(-50, 'UTC-5 Eastern Time(US & Canada)'),
	) 

def now():
	return DateTime.now()

def to_time(d):
	if isinstance(d, DateTime):
		return time.mktime(d.timetuple())
	return 0.0

def is_email(email):
	r = re.compile(r'^[\w\+]+(\.[\w\+]+)*@\w+(\.\w+)*$', re.IGNORECASE)
	m = r.match(email)
	if m is not None:
		return True
	return False

def start_of_today():
	d = now()
	return DateTime(d.year, d.month, d.day, 0, 0, 0)

def to_str(obj):
	if obj is None:
		return ''
	if isinstance(obj, list) or isinstance(obj, tuple):
		if len(obj)>0:
			return to_str(obj[0])
	if isinstance(obj, str):
		return obj
	elif isinstance(obj, unicode):
		return obj.encode("utf-8", "ignore")
	return '%s' % obj

def to_utf8(obj):
	if obj is None:
		return u''
	if isinstance(obj, list) or isinstance(obj, tuple):
		if len(obj)>0:
			return to_utf8(obj[0])
	if isinstance(obj, unicode):
		return obj
	elif isinstance(obj, str):
		return obj.decode("utf-8", "ignore")
	return u'%s' % obj

def find(items, func):
	for item in items:
		if func(item):
			return item
	return None

def findall(items, func):
	return [item for item in items if func(item)]
	#for item in items:
	#	if func(item):
	#		yield item

def distinct(items, func=None):
	if func is None:
		func = lambda x:x
	result_indexes = []
	[result_indexes.append(func(item)) for item in items if func(item) not in result_indexes]
	results = []
	[results.append(item) for item in items if item not in results and func(item) in result_indexes]
	return results


# ------------

def get_exname(filename):
	r = r'(?P<exname>\.[a-zA-Z0-9_]+)$'
	m = re.search(r, filename)
	if m is not None:
		return m.group('exname').strip()
	return ""

_safe_exnames = (".jpg",".gif",".png",".jpe",".jpeg",".bmp",".swf",)

def is_safe_exname(exname):
	for n in _safe_exnames:
		if n==exname.lower():
			return True
	return False

def save_upload_file(uploadfile, folder, createprefix=True):
	'''this method is for Bottle framework'''
	fail_msg = ""
	if uploadfile is None:
		return {
			'fail': 'The field is None.'
		}
	if not os.access(folder, os.F_OK):
		os.makedirs(folder)
	if os.access(folder, os.F_OK or os.W_OK):
		f = uploadfile
		original_name = f.filename
		exname = get_exname(original_name)
		if exname and is_safe_exname(exname):
			mainpart = str(guid())
			filename = "%s%s" % (mainpart, exname)
			if createprefix:
				prefix = filename[0:2]
				final_folder = "%s/%s" % (folder, prefix)
				if not os.access(final_folder, os.F_OK):
					os.mkdir(final_folder)
			else:
				final_folder = folder
			#
			# size = f.length
			filedata = f.file.read()
			size = len(filedata)
			# TODO:cal md5
			hashstr = hashlib.md5(filedata).hexdigest()
			filename = '%s%s' % (hashstr[:16], exname) 
			localpath = "%s/%s" % (final_folder, filename)
			dstfile = open(localpath, "wb+")
			dstfile.write(filedata)
			dstfile.close()
			return {
				'filename': filename,
				'exname': exname,
				'ext': exname,
				'original_name': original_name,
				'size': size,
				'path': localpath
			}
		else:
			if exname:
				fail_msg = "Unsafe file type(%s)." % exname
			else:
				fail_msg = "Invalid file type(filename = %s)." % f.name
	else:
		fail_msg = "%s is inaccessible." % folder
	return { 'fail': fail_msg }

def _save_upload_file(uploadfile, folder, createprefix=True):
	'''this method is a upload saving method for Django'''
	fail_msg = ""
	if uploadfile is None:
		return {
			'fail': 'The field is None.'
		}
	if not os.access(folder, os.F_OK):
		os.makedirs(folder)
	if os.access(folder, os.F_OK or os.W_OK):
		f = uploadfile
		original_name = f.name
		exname = get_exname(f.name)
		if exname and is_safe_exname(exname):
			mainpart = str(guid())
			filename = "%s%s" % (mainpart, exname)
			if createprefix:
				prefix = filename[0:2]
				final_folder = "%s/%s" % (folder, prefix)
				if not os.access(final_folder, os.F_OK):
					os.mkdir(final_folder)
			else:
				final_folder = folder
			#
			size = f.size
			localpath = "%s/%s" % (final_folder, filename)
			dstfile = open(localpath, "wb+")
			if f.multiple_chunks():
				for part in f.chunks():
					dstfile.write(part)
			else:
				dstfile.write(f.read())
			dstfile.close()
			return {
				'filename': filename,
				'exname': exname,
				'ext': exname,
				'original_name': original_name,
				'size': size,
				'path': localpath
			}
		else:
			if exname:
				fail_msg = "Unsafe file type(%s)." % exname
			else:
				fail_msg = "Invalid file type(filename = %s)." % f.name
	else:
		fail_msg = "%s is inaccessible." % folder
	return { 'fail': fail_msg }


class LocationInfo(object):	
	def __init__(self, country='', province='', city='', district=''):
		self.country = country
		self.province = province
		self.city = city
		self.district = district
	
	def __str__(self):
		# return '%s\r\n%s' % (self.province, self.city)
		return json.dumps({'country':'', 'province':self.province, 'city':self.city, 'district':''})

class UploadedFile(object):
	
	def __init__(self, file):
		self.file = file
	
	def save(self, folder, createprefix=False):
		return save_upload_file(self.file, folder, createprefix)


class Coordinates(object):
	def __init__(self, lat=0.0, lng=0.0):
		self.lat = lat
		self.lng = lng
	
	@property
	def lat(self):
		return self._lat
	
	@lat.setter
	def lat(self, value):
		self._lat = Decimal('%s' % value)
	
	@property
	def lng(self):
		return self._lng
	
	@lng.setter
	def lng(self, value):
		self._lng = Decimal('%s' % value)
	
	def __str__(self):
		return json.dumps({"lat":'%s' % self.lat, "lng":'%s' % self.lng})
	
	



